package com.fuershiye.woman.monitor.service.impl;

import com.fuershiye.woman.monitor.beans.*;
import com.fuershiye.woman.monitor.constants.Massage;
import com.fuershiye.woman.monitor.constants.ReportType;
import com.fuershiye.woman.monitor.enums.CodeRelationEnum;
import com.fuershiye.woman.monitor.model.Area;
import com.fuershiye.woman.monitor.model.DepartIndicator;
import com.fuershiye.woman.monitor.model.Department;
import com.fuershiye.woman.monitor.model.Indicator;
import com.fuershiye.woman.monitor.service.*;
import com.fuershiye.woman.monitor.utils.Math;
import com.fuershiye.woman.monitor.utils.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author admin
 */
@Service("reportService")
public class ReportServiceImpl implements ReportService {

    private static final Logger logger = LoggerFactory.getLogger(ReportService.class);

    @Autowired
    private DepartIndicatorService departIndicatorService;
    @Autowired
    private IndicatorService indicatorService;
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private AreaService areaService;

    @Override
    public Result saveReport(Long id, Integer year, Integer type, Double value, String editor, String remark) {

        logger.info("saveReport log id:{}, year:{}, type:{}, value:{}, editor:{}, remark:{}",
                id,year,type,value,editor,remark);

        if(id==null||id==0||!DateFormatUtil.isYear(year) || !ReportType.containId(type)){
            return new Result(Massage.ERROR_PARAMETER);
        }
        DepartIndicator departIndicator = departIndicatorService.get(id);
        if(departIndicator==null){
            return new Result(Massage.REPORT_IS_NULL);
        }
        Indicator indicator = indicatorService.get(departIndicator.getIndicator());
        if(indicator==null){
            return new Result(Massage.INDICATOR_IS_NULL);
        }

        // 保存好当前指标，上报的数据
        departIndicator = saveData(departIndicator, indicator.getRule(), indicator.getAim(), editor, year, remark, type, value);

        String code = indicator.getCode();
        // 根据code码判断是否需要填充保存其他数据
        if(null!=CodeRelationEnum.getByCodeUp(code)
                || null!=CodeRelationEnum.getByCodeDown(code)){
            appendSaveData(code, departIndicator, year);
        }
        return new Result(Massage.SUCCESS);
    }

    // 上报的是分子或分母数据时，都有可能影响待计算数据，所以都需要更新
    private void appendSaveData(String codeReal, DepartIndicator samedepartIndicator, int year){

        String codeAppend=""; // 需要追加的code
        String codeUp=""; // 分子的code
        String codeDown=""; // 分母的code

        DepartIndicator appendDI = new DepartIndicator();
        DepartIndicator upDI = new DepartIndicator();;
        DepartIndicator downDI = new DepartIndicator();;

        Indicator indicatorAppend = new Indicator();
        Long indicatorIdUp;
        Long indicatorIdDown;

        long departid = samedepartIndicator.getDepartid();
        long forms = samedepartIndicator.getForms();
        // 上报分子的数值时，需要计算出关联指标的值
        if(null!=CodeRelationEnum.getByCodeUp(codeReal)){
            codeAppend=CodeRelationEnum.getByCodeUp(codeReal).getCode();
            codeUp=codeReal;
            codeDown=CodeRelationEnum.getByCodeUp(codeReal).getCodeDown();

            indicatorAppend = indicatorService.findByCodeForms(codeAppend, forms);
            indicatorIdDown = indicatorService.getIdByCodeForms(codeDown, forms);

            upDI = samedepartIndicator;
            appendDI = departIndicatorService.findByCondition(departid, forms, indicatorAppend.getId(), year, 1);
            downDI = departIndicatorService.findByCondition(departid, forms, indicatorIdDown, year, 1);

            // 上报分母的数值时，需要计算出关联指标的值
        }else if(null!=CodeRelationEnum.getByCodeDown(codeReal)) {
            codeAppend=CodeRelationEnum.getByCodeDown(codeReal).getCode();
            codeUp=CodeRelationEnum.getByCodeDown(codeReal).getCodeUp();
            codeDown=codeReal;

            indicatorAppend = indicatorService.findByCodeForms(codeAppend, forms);
            indicatorIdUp = indicatorService.getIdByCodeForms(codeUp, forms);

            appendDI = departIndicatorService.findByCondition(departid, forms, indicatorAppend.getId(), year, 1);
            upDI = departIndicatorService.findByCondition(departid, forms, indicatorIdUp, year, 1);
            downDI = samedepartIndicator;
        }else {
            return;
        }
        logger.info("codeAppend:{},codeUp:{},codeDown:{}", codeAppend, codeUp, codeDown);

        double valueAppend=0;
        if(null==indicatorAppend||
                null==appendDI||null==upDI||null==downDI||
                Math.isNull(upDI.getRvalue())||Math.isNull(downDI.getRvalue())
        ){
            logger.error("Indicator or DepartIndicator or value is null");
        }else {
            valueAppend = Math.divideAB(upDI.getRvalue(), downDI.getRvalue());
        }
        saveData(appendDI, indicatorAppend.getRule(), indicatorAppend.getAim(), samedepartIndicator.getEditor(), year, "", samedepartIndicator.getRtype(), valueAppend);
    }

    private DepartIndicator saveData(DepartIndicator saveDI,  int rule, Double aim, String editor, int year, String remark, int type, Double value){

        saveDI = ObjectUtil.buildDepartIndicator(saveDI, editor, year, remark, type, value);
        Double lastYearValue = departIndicatorService.getValueByCondition(saveDI.getDepartid(),saveDI.getForms(),saveDI.getIndicator(),saveDI.getYear()-1,1);
        Double last2YearValue = departIndicatorService.getValueByCondition(saveDI.getDepartid(),saveDI.getForms(),saveDI.getIndicator(),saveDI.getYear()-2,1);
        saveDI.setRshow(getLevel(saveDI, rule, aim, lastYearValue, last2YearValue));
        logger.info("saveID:{}", saveDI.getId());

        try {
            departIndicatorService.updateDepartValue(saveDI);
        }catch (Exception e){
            logger.error("saveData exception e:{}", e);
        }
        return saveDI;
    }

    //终期目在指标表里，当年目标值在上报数据表里，根据这两个值去获取应当显示的颜色
    private int getLevel (DepartIndicator departIndicator, int rule, Double aim, Double lastYearValue, Double last2YearValue){

        Integer showLevelSD = ReportUtil.getSDShowLevel(
                departIndicator.getRtype(), rule, aim, departIndicator.getAvalue(), departIndicator.getRvalue(),
                lastYearValue, last2YearValue);

        return showLevelSD==null? 0:showLevelSD;

    }

    @Override
    public List<ViewReportAllValue> getReportDate(List<Long> departIds, Long forms, List<Long> indicators, List<Integer> years, Integer status) {

        List<ViewDepartIndicatorReport> result = Lists.newArrayList();
        for (int year : years) {
            result.addAll(departIndicatorService.listByCondition(departIds, forms, indicators, year, status, new Page(1, Integer.MAX_VALUE)));
        }
//        所有年份数据都已获取，把多个年份的数据根据 根据 departid、forms、indicator 转换为一条数据
        List<ViewDepartIndicatorValue> listVdi = ObjectUtil.mergeViewReport(result);

        return appendDepartAndIndicator(listVdi);
    }

    /**
     * 补充部门、地域和指标信息
     * @param listVdi
     * @return
     */
    private List<ViewReportAllValue> appendDepartAndIndicator(List<ViewDepartIndicatorValue> listVdi) {

        List<ViewReportAllValue> result = Lists.newArrayList();

        if(listVdi.isEmpty()){
            return result;
        }

        for (ViewDepartIndicatorValue vdi : listVdi) {
            if(null==vdi||null==vdi.getIndicator()||null==vdi.getDepartid()){
                continue;
            }
            Indicator indicator =  indicatorService.get(vdi.getIndicator());
            Department department =  departmentService.get(vdi.getDepartid());
            if(null==department||null==department.getArea()){
                continue;
            }
            Area area =  areaService.get(department.getArea());
            ViewReportAllValue vrv = ReportUtil.vdi2Vrv(vdi);
            ViewReportAllValue vrvd = ObjectUtil.appendDepart(vrv, department);
            ViewReportAllValue vrva = ObjectUtil.appendArea(vrvd, area);
            ViewReportAllValue vrvi = ObjectUtil.appendIndicator(vrva, indicator);
            result.add(vrvi);
        }

        return result;
    }

    /**
     *
     map.put("id", vdi.getId());
     map.put("departid", vdi.getDepartid());
     map.put("indicator", vdi.getIndicator());
     map.put("formsid", vdi.getForms());
     map.put("code", vdi.getCode());
     map.put("places", vdi.getPlaces());
     map.put("iname", vdi.getIname());
     map.put("sname", vdi.getSname());
     map.put("unit", vdi.getUnit());
     map.put("indicatorType", vdi.getIndicatorType());
     map.put("supplement", vdi.getSupplement());
     map.put("aim", vdi.getAim());
     map.put("rule", vdi.getRule());
     map.put("rname", vdi.getRname());
     map.put("idesc", vdi.getIdesc());
     map.put("2010", viewReportAllValue.getT10()+"_"+viewReportAllValue.getA10()+"_"+viewReportAllValue.getV10()+"_"+viewReportAllValue.getS10()+"_"+viewReportAllValue.getR10()+"");
     map.put("2011", viewReportAllValue.getT11()+"_"+viewReportAllValue.getA11()+"_"+viewReportAllValue.getV11()+"_"+viewReportAllValue.getS11()+"_"+viewReportAllValue.getR11()+"");

     * @param firstList
     * @param secondList
     * @param year
     * @return
     */
    @Override
    public List<Map<String, Object>> merge(List<Map<String, Object>> firstList, List<Map<String, Object>> secondList, Integer year) {

        List<Map<String, Object>> result = Lists.newArrayList();

        if(firstList.isEmpty()){
            return result;
        }

        for (Map<String, Object> map : firstList) {
            String key = map.get("departid").toString()+map.get("indicator").toString()+map.get("formsid").toString();
            map.put(year-1+"", getSameKey(key, secondList, year));
            result.add(map);
        }

        return SortUtil.sortListByAreaCode(result);
    }

    /**
     * @param key
     * @param list
     * @return
     */
    public String getSameKey(String key, List<Map<String, Object>> list, Integer year) {

        if(key.isEmpty()){
            return "";
        }

        for (Map<String, Object> map : list) {
            String keyAim = map.get("departid").toString()+map.get("indicator").toString()+map.get("formsid").toString();
            if(keyAim.equals(key)){
                return map.get(year-1+"").toString();
            }
        }
        return "";
    }

    /**
     *
     * @param listVrv
     * @return
     */
    @Override
    public List<Map<String, Object>> filter(List<ViewReportAllValue> listVrv, List<Integer> years) {

        List<Map<String, Object>> result = Lists.newArrayList();

        if(listVrv.isEmpty()){
            return result;
        }
        for (ViewReportAllValue vdi : listVrv) {
            result.add(turnVdi2Map(vdi, years));
        }

        return SortUtil.sortListByAreaCode(result);
    }

    /**
     *
     * @param listVrv
     * @return
     */
    @Override
    public List<Map<String, Object>> filter(List<ViewReportAllValue> listVrv, List<Integer> years, List<Long> departIds) {

        List<Map<String, Object>> result = Lists.newArrayList();

        if(listVrv.isEmpty()){
            return result;
        }
//      一条记录 ViewReportAllValue，根据（departid、forms、indicator）合并成一行，已经包含了多年的数据
        List<ViewReportAllValue> list = appendReportDate(listVrv, departIds, years);
        list = deleteRepeat(list);

        for (ViewReportAllValue vdi : list) {
            result.add(turnVdi2Map(vdi, years));
        }
        return SortUtil.sortListByAreaCode(result);

    }

    private List<ViewReportAllValue> deleteRepeat(List<ViewReportAllValue> list) {

        List<ViewReportAllValue> result = Lists.newArrayList();

        if (list.isEmpty()) {
            return result;
        }

        Set<Long> exist = Sets.newConcurrentHashSet();
        // 根据指标父子关系补充其他指标
        for (ViewReportAllValue vdi : list) {

            if(exist.contains(vdi.getIndicator())){
                continue;
            }
            result.add(vdi);
            exist.add(vdi.getIndicator());
        }
        return result;
    }

    /**
     * 仅处理同年份、指标依赖、组合关系的数据
     *
     * @param list
     * @param departIds
     * @return
     */

    private List<ViewReportAllValue> appendReportDate(List<ViewReportAllValue> list, List<Long> departIds, List<Integer> years){

        List<ViewReportAllValue> result = Lists.newArrayList();

        if(list.isEmpty()){
            return result;
        }

        // 根据指标父子关系补充其他指标
        for (ViewReportAllValue vdi : list) {
            result.add(vdi);

            //没有配置父子关系类型的跳过、没有父指标的跳过
            if(vdi.getPrule()==null||vdi.getPid()==null){
                continue;
            }

            switch(vdi.getPrule()) {
                case 0:
                    //默认无父子关系的无需追加
                    break;
                case 1:
                    //需要补充其他部门上报的数据
                    List<ViewReportAllValue> listAppendOther = appendOtherDepartDate(vdi, departIds, years);
                    result.addAll(listAppendOther);

                    //父子关系为同部门上报的数据,父指标的数据只需展示"-"
                    ViewReportAllValue mergeShow = mergeParentDepartDate(vdi, departIds, years, true);
                    result.add(mergeShow);
                    break;
                case 2:
                    //需要补充其他部门上报的数据
                    List<ViewReportAllValue> listVrvTemp = appendOtherDepartDate(vdi, departIds, years);
                    result.addAll(listVrvTemp);
                    break;
                case 3:
                    //需要同部门合并的数据
                    ViewReportAllValue mergeData = mergeParentDepartDate(vdi, departIds, years, false);
                    result.add(mergeData);
                    break;
                case 4:
                    //补充其他部门上报的数据，并且合并所有部门的数据
                    List<ViewReportAllValue> listSameParentTemp = appendOtherDepartDate(vdi, departIds, years);
                    result.addAll(listSameParentTemp);

                    ViewReportAllValue mergeSameParentData = mergeParentDepartDate(vdi, departIds, years, false);
                    result.add(mergeSameParentData);
                    break;
//                case 5:
//                    //需要父/子指标数据相除
//                    ViewReportAllValue divideData = divideParentDepartData(vdi, departIds, years, false);
//                    result.add(divideData);
//                    break;
                default:
            }
        }
        return result;
    }

    // 获取同父指标，其他部门上报的数据
    private List<ViewReportAllValue> appendOtherDepartDate(ViewReportAllValue vdi, List<Long> departIds, List<Integer> years){

        List<Indicator> indicatorList = indicatorService.getByPidForms(vdi.getPid(), vdi.getForms(), 1);
        List<Long> indicators = indicatorService.getIndicatorId(indicatorList);

        List<ViewDepartIndicatorReport> result = Lists.newArrayList();
        for (Integer year : years) {
            result.addAll(departIndicatorService.listByCondition(departIds, vdi.getForms(), indicators, year, 1, new Page(1, Integer.MAX_VALUE)));
        }

        List<ViewDepartIndicatorValue> listVdi = ObjectUtil.mergeViewReport(result);
        return appendDepartAndIndicator(listVdi);
    }

    // 父指标数据是所有子指标数据之和
    private ViewReportAllValue mergeParentDepartDate(ViewReportAllValue vdi, List<Long> departIds, List<Integer> years, boolean onlyShow){

        ViewReportAllValue result = new ViewReportAllValue();
        Indicator prentIndicator = indicatorService.get(vdi.getPid());
        result = ObjectUtil.appendIndicator(result, prentIndicator);
        result.setId(9999999L);
        result.setAreaid(999999L);
        result.setDepartid(999999L);
        result.setForms(vdi.getForms());
        result.setYear(vdi.getYear());

        List<Indicator> indicatorList = indicatorService.getByPidForms(vdi.getPid(), vdi.getForms(), 1);
        List<Long> indicators = indicatorService.getIndicatorId(indicatorList);

        for (Integer year : years) {
            List<ViewDepartIndicatorReport> vdir = departIndicatorService.listByCondition(departIds, vdi.getForms(), indicators, year, 1, new Page(1, Integer.MAX_VALUE));

            Double count = new Double(0L);
            for (ViewDepartIndicatorReport vdiSon : vdir) {
                if(vdiSon.getRvalue()!=null){
                    count+=vdiSon.getRvalue();
                }
            }

            ViewDepartIndicatorReport temp = new ViewDepartIndicatorReport();
            temp.setRtype(vdir.get(0).getRtype());
            temp.setRemark(vdir.get(0).getRemark());
            temp.setAvalue(vdir.get(0).getAvalue());
            temp.setRshow(vdir.get(0).getRshow());
            if(onlyShow){
                result.setAname("--");
                result.setSname("--");
                result.setPlaces(null);
                temp.setRvalue(null);
            }else{
                result.setAname("合计");
                result.setSname("合计");
                temp.setRvalue(count);
            }
            result = ReportUtil.mergeReport2One(result, temp, year);
        }
        return result;
    }

//    // 父指标数据是所有子指标数据之和
//    private ViewReportAllValue divideParentDepartData(ViewReportAllValue vdi, List<Long> departIds, List<Integer> years, boolean onlyShow){
//
//        ViewReportAllValue result = new ViewReportAllValue();
//        Indicator prentIndicator = indicatorService.get(vdi.getPid());
//        result = ObjectUtil.appendIndicator(result, prentIndicator);
//        result.setId(9999999L);
//        result.setAreaid(999999L);
//        result.setDepartid(999999L);
//        result.setForms(vdi.getForms());
//        result.setYear(vdi.getYear());
//
//        List<Indicator> indicatorList = indicatorService.getByPidForms(vdi.getPid(), vdi.getForms(), 1);
//        List<Long> indicators = indicatorService.getIndicatorId(indicatorList);
//
//        for (Integer year : years) {
//            List<ViewDepartIndicatorReport> vdirParent = departIndicatorService.listByCondition(departIds, vdi.getForms(), indicators, year, 1, new Page(1, Integer.MAX_VALUE));
//            if(onlyShow){
//                result.setAname("--");
//                result.setSname("--");
//                result.setPlaces(null);
//            }else{
//                result.setAname("数值");
//                result.setSname("数值");
//            }
//            result = ReportUtil.setReportValue(result, vdirParent.get(0).getRvalue(), year);
//        }
//        return result;
//    }

    /**
     *
     * @param list
     * @return
     */
    @Override
    public Map<String, List<ViewReportAllValue>> filter(List<ViewReportAllValue> list) {

        Map<String, List<ViewReportAllValue>> result = Maps.newHashMap();

        if(list.isEmpty()){
            return result;
        }

        for (ViewReportAllValue vdi : list) {
            if(null==vdi){
                continue;
            }

            String key = vdi.getIndicator().toString();
            if(result.containsKey(key)){
                List<ViewReportAllValue> listDepart = result.get(key);
                listDepart.add(vdi);
            }else{
                List<ViewReportAllValue> listDepart = Lists.newArrayList();
                listDepart.add(vdi);
                result.put(key, listDepart);
            }
        }
        return result;
    }


    /**
     *
     * @param list
     * @param year
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> axis(Map<String, List<ViewReportAllValue>> list, Integer year) {

        List<Map<String, Object>> result = Lists.newArrayList();
        if(list.isEmpty()){
            return result;
        }
        List<Integer> years = Lists.newArrayList();
        years.add(year);

        // 同一个指标，不同的部门
        for (String key : list.keySet()) {
            List<ViewReportAllValue> listDepart = list.get(key);
            if(listDepart.size()<1){
                continue;
            }
            Map<String, Object> map = turnVdi2Map(listDepart.get(0), years);
            List<Map<String, Object>> listDepartValue = Lists.newArrayList();
            BigDecimal sumValue = new BigDecimal("0");
            for (ViewReportAllValue vdi: listDepart){
                Map<String, Object> subMap = Maps.newHashMap();
                subMap.put("departid", vdi.getDepartid());
                subMap.put("sname", vdi.getAname());
                subMap = ReportUtil.getYearReport(subMap, year, vdi);
                Double value = ReportUtil.getValueByYear(vdi, year);
                Double tempResult = (value== null ? 0:value);
                sumValue = Math.addBigDecimal(sumValue.toString(), tempResult.toString());
                listDepartValue.add(subMap);
            }
            String sum = "";
            if(sumValue!=null && listDepart.size()>0){
                sum = String.format("%.2f", sumValue.doubleValue() / listDepart.size());
            }
            listDepartValue.add(getSumMap(year, sum));
            map.put("list", SortUtil.sortListByDepartPreset(listDepartValue));
            result.add(map);
        }
        return result;
    }

// 计算平均值
//            {
//                "2016": "1_0_13615_0_",
//                    "sname": "济宁统计",
//                    "departid": 44
//            },
    private Map<String, Object> getSumMap(Integer year, String value){
        Map<String, Object> sumMap = Maps.newHashMap();
        sumMap.put(year+"","1_0_"+value+"_0_");
        sumMap.put("sname","均值");
        sumMap.put("departid","0");
        return sumMap;
    }
    /**
     *
     * @param list
     *
     * @return
     */
    @Override
    public List<ViewReportAllValue> appendPidName(List<ViewReportAllValue> list){
        List<ViewReportAllValue> result = Lists.newArrayList();

        if(list.isEmpty()){
            return result;
        }

        for (ViewReportAllValue vdi : list) {
            if(null==vdi){
                continue;
            }

            if(vdi.getPrule()!=null && vdi.getPrule()!=0){
                Indicator pIndicator = indicatorService.get(vdi.getPid());
                if(pIndicator!=null){
                    vdi.setIname(pIndicator.getName()+"（"+vdi.getIname()+"）");
                }else{
                    vdi.setIname(vdi.getIname());
                }
            }
            result.add(vdi);
        }

        return result;
    }

    private Map<String, Object> turnVdi2Map(ViewReportAllValue vdi, List<Integer> years){

        Map<String, Object> map = Maps.newHashMap();
        if(null==vdi){
            return map;
        }

        map.put("id", vdi.getId());
        map.put("departid", vdi.getDepartid());
        map.put("indicator", vdi.getIndicator());
        map.put("formsid", vdi.getForms());
        map.put("code", vdi.getCode());
        map.put("places", vdi.getPlaces());
        map.put("iname", vdi.getIname());
        map.put("sname", vdi.getSname());
        map.put("unit", vdi.getUnit());
        map.put("indicatorType", vdi.getIndicatorType());
        map.put("supplement", vdi.getSupplement());
        map.put("aim", vdi.getAim());
        map.put("rule", vdi.getRule());
        map.put("rname", vdi.getRname());
        map.put("idesc", vdi.getIdesc());

        for (Integer year : years) {
            if(year!=null){
                map = ReportUtil.getYearReport(map, year, vdi);
                //默认塞一个值进去
                map.put("rtype", getRtypeByYear(map, year));
                map.put("remark", getRemarkByYear(map, year));
            }
        }
        return map;
    }

    private String getRemarkByYear(Map<String, Object> map, Integer year){
        if(!map.containsKey(year+"")){
            return "";
        }
        String valueYear = map.get(year+"").toString();
        if(valueYear.isEmpty()){
            return "";
        }
//		valueYear = 数据上报的类型_每年的目标值_数值_显示数据展示时效果的规则_每年的备注
        String[] valueYeararry = valueYear.split("_");
        return valueYear.split("_",-1)[4];
    }

    private String getRtypeByYear(Map<String, Object> map, Integer year){
        if(!map.containsKey(year+"")){
            return "0";
        }
        String valueYear = map.get(year+"").toString();
        if(valueYear.isEmpty()){
            return "0";
        }
//		valueYear = 数据上报的类型_每年的目标值_数值_显示数据展示时效果的规则_每年的备注
        String[] valueYeararry = valueYear.split("_");
        return valueYear.split("_",-1)[0];
    }

}
